#pragma once
/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * Standard File Class
 *      Provides a managed wrapper for the standard C file I/O operations.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
#include "stdafx.h"
#include "DisposableObjectBase.h"

using namespace System;
using namespace System::IO;
using namespace Adaptive::Foundation;

namespace Adaptive
{
	namespace Foundation
	{
		namespace IO
		{
			/// <summary>
			/// Provides a managed wrapper for the standard C file I/O operations.
			/// </summary>
			public ref class StdFile : public DisposableObjectBase
			{
				public:
				/*--------------------------------------------------------------------------------
				 * Public Event Definitions
				 *------------------------------------------------------------------------------*/
				#pragma region Public Event Definitions
				/// <summary>
				/// Occurs when the underlying file handle is opened.
				/// </summary>
				event EventHandler^ FileOpened;
				/// <summary>
				/// Occurs when the underlying file handle is closed.
				/// </summary>
				event EventHandler^ FileClosed;
				#pragma endregion

				/*--------------------------------------------------------------------------------
				 * Constructor / Dispose / Destructor Methods
				 *------------------------------------------------------------------------------*/
				#pragma region Constructor / Dispose / Destructor Methods
				/// <summary>
				/// Initializes a new instance of the class.
				/// </summary>
				/// <remarks>
				/// This is the default constructor.
				/// </remarks>
				StdFile();
				/// <summary>
				/// Initializes a new instance of the class.
				/// </summary>
				/// <param name="fileHandle">An <see cref="IntPtr"/> value containing the file or device handle being opened.</param>
				StdFile( IntPtr fileHandle);
				/// <summary>
				/// Initializes a new instance of the class.
				/// </summary>
				/// <param name="fileName">The name of the file to be opened.</param>
				StdFile( String^ fileName );
				/// <summary>
				/// Initializes a new instance of the class.
				/// </summary>
				/// <param name="fileName">The name of the file to be opened.</param>
				/// <param name="mode">A <see cref="FileMode"/> enumerated value indicating how the file is to be opened.</param>
				/// <param name="access">A <see cref="FileAccess"/> enumerated value indicating the access rights. </param>
				/// <param name="shareMode">A <see cref="FileShare"/> enumerated value indicating how the file is to be shared.</param>
				StdFile( String^ fileName, FileMode mode, FileAccess access, FileShare shareMode );
				/// <summary>
				/// Deallocates internally allocated objects.
				/// </summary>
				~StdFile();
				#pragma endregion

				/*--------------------------------------------------------------------------------
				 * Public Properties
				 *------------------------------------------------------------------------------*/
				#pragma region Public Properties
				/// <summary>
				/// Gets a value indicating whether the file is open.
				/// </summary>
				/// <value>
				/// <b>true</b> if the file is open; otherwise, <b>false</b>.
				/// </value>
				property bool IsOpen { inline bool get(); }
				/// <summary>
				/// Gets a value indicating whether the end of the file has been reached.
				/// </summary>
				/// <value>
				/// <b>true</b> if the current position is at the end of the file; otherwise, <b>false</b>.
				/// </value>
				property bool Eof { inline bool get(); }
				/// <summary>
				/// Gets or sets the current byte position of the file pointer.
				/// </summary>
				/// <value>
				/// The current read/write position within the file, in bytes.
				/// </value>
				property long Position { long get(); void set(long value); }
				/// <summary>
				/// Gets the size of the file, in bytes.
				/// </summary>
				/// <value>
				/// The total size of the file, in bytes.
				/// </value>
				property long FileSize { inline long get(); }
				#pragma endregion
	 
				/*--------------------------------------------------------------------------------
				 * Public Methods / Functions
				 *------------------------------------------------------------------------------*/
				#pragma region Public Methods / Functions
				/// <summary>
				/// Closes the file, if open.
				/// </summary>
				/// <remarks>
				/// This wraps the C <b>fclose</b> function.
				/// </remarks>
				void Close();
				/// <summary>
				/// Flushes the content of the file buffer to disk.
				/// </summary>
				/// <remarks>
				/// This wraps the C <b>fflush</b> function.
				/// </remarks>
				void Flush();
				/// <summary>
				/// Opens the specified file for read and write access.
				/// </summary>
				/// <param name="fileName">The name of the file to be opened.</param>
				void Open(String^ fileName);
				/// <summary>
				/// Opens the specified file for the specified mode and access.
				/// </summary>
				/// <param name="fileName">The name of the file to be opened.</param>
				/// <param name="mode">A <see cref="FileMode"/> enumerated value indicating how the file is to be opened.</param>
				/// <param name="access">A <see cref="FileAccess"/> enumerated value indicating the access rights. </param>
				/// <param name="shareMode">A <see cref="FileShare"/> enumerated value indicating how the file is to be shared.</param>
				void Open(String^ fileName, FileMode mode, FileAccess access, FileShare shareMode);
				/// <summary>
				/// Opens access with the specified file handle.
				/// </summary>
				/// <param name="fileHandle">An open file or device handle.</param>
				void Open(IntPtr fileHandle);
				/// <summary>
				/// Provides a static mechanusm for opening a file with the specified name and access parameters.
				/// </summary>
				/// <param name="fileName">The name of the file to be opened.</param>
				/// <param name="mode">A <see cref="FileMode"/> enumerated value indicating how the file is to be opened.</param>
				/// <param name="access">A <see cref="FileAccess"/> enumerated value indicating the access rights. </param>
				/// <param name="shareMode">A <see cref="FileShare"/> enumerated value indicating how the file is to be shared.</param>
				/// <returns>
				/// A new <see cref="StdFile"/> instance if successful, otherwise, <b>null</b>.
				/// </returns>
				static StdFile^ OpenFile(String^ fileName, FileMode mode, FileAccess access, FileShare shareMode);
				/// <summary>
				/// Reads the next character from the stream.
				/// </summary>
				/// <remarks>
				/// This wraps the C <b>_fgettc</b> function.
				/// </remarks>
				/// <returns>
				/// The character read from the stream.
				/// </returns>
				Char ReadCharacter();
				/// <summary>
				/// Reads the next wide character from the stream.
				/// </summary>
				/// <remarks>
				/// This wraps the C <b>_fgettwc</b> function.
				/// </remarks>
				/// <returns>
				/// The character read from the stream.
				/// </returns>
				Char ReadWideCharacter();
				/// <summary>
				/// Reads the next byte from the stream.
				/// </summary>
				/// <remarks>
				/// This wraps the C <b>_fgettc</b> function.
				/// </remarks>
				/// <returns>
				/// The character read from the stream.
				/// </returns>
				Byte ReadByte();
				/// <summary>
				/// Reads a string from the stream.
				/// </summary>
				/// <param name="stringLength">The size of the string to read.</param>
				/// <remarks>
				/// This wraps the C <b>_fgetts</b> function.
				/// </remarks>
				/// <returns>
				/// The string read from the stream, or <b>null</b> if the operation fails.
				/// </returns>
				String^ ReadString( int stringLength );
				/// <summary>
				/// Reads a string from the stream.
				/// </summary>
				/// <param name="stringLength">The size of the string to read.</param>
				/// <remarks>
				/// This wraps the C <b>_fgetws</b> function.
				/// </remarks>
				/// <returns>
				/// The string read from the stream, or <b>null</b> if the operation fails.
				/// </returns>
				String^ ReadWideString( int stringLength );
				/// <summary>
				/// Writes a string to the stream.
				/// </summary>
				/// <param name="textToWrite">The text to be written.</param>
				/// <remarks>
				/// This wraps the C <b>_fputs</b> function.
				/// </remarks>
				void	WriteString( String^ textToWrite );
				/// <summary>
				/// Writes a string to the stream.
				/// </summary>
				/// <param name="textToWrite">The text to be written.</param>
				/// <remarks>
				/// This wraps the C <b>_fputws</b> function.
				/// </remarks>
				void	WriteWideString( String^ textToWrite );
				/// <summary>
				/// Writes a character to the stream.
				/// </summary>
				/// <param name="characterToWrite">The character to be written.</param>
				/// <remarks>
				/// This wraps the C <b>_fputc</b> function.
				/// </remarks>
				void	WriteCharacter(Char characterToWrite );
				/// <summary>
				/// Writes a unicode character to the stream.
				/// </summary>
				/// <param name="characterToWrite">The character to be written.</param>
				/// <remarks>
				/// This wraps the C <b>_fputwc</b> function.
				/// </remarks>
				void	WriteWideCharacter(Char characterToWrite );
				/// <summary>
				/// Reads the specified number of bytes from the stream into the 
				/// specified buffer.
				/// </summary>
				/// <param name="buffer">A byte array to be filled with data read from the stream.</param>
				/// <param name="bufferSize">The number of bytes to be read.</param>
				/// <remarks>
				/// This wraps the C <b>fread</b> function.
				/// </remarks>
				/// <returns>
				/// The actual number of bytes read from the stream.
				/// </returns>
				int		ReadBytes(array<Byte>^ buffer, int bufferSize);
				/// <summary>
				/// Writes the byte array to the stream.
				/// </summary>
				/// <param name="buffer">A byte array to write to the stream.</param>
				/// <remarks>
				/// This wraps the C <b>fwrite</b> function.
				/// </remarks>
				void	WriteBytes(array<Byte>^ buffer);
				/// <summary>
				/// Moves the file pointer to the specified byte position.
				/// </summary>
				/// <param name="offset">The byte offset from the specified position.</param>
				/// <param name="origin">A <see cref="SeekOrigin"/> enumerated value indicating the position from which the offset is calculated.</param>
				/// <remarks>
				/// This wraps the C <b>fseek</b> function.
				/// </remarks>
				void	Seek( long offset, SeekOrigin origin);
				/// <summary>
				/// Rewinds the stream.
				/// </summary>
				/// <remarks>
				/// This wraps the C <b>rewind</b> function.
				/// </remarks>
				void	Rewind();
				#pragma endregion

				private:
				/*--------------------------------------------------------------------------------
				 * Private Member Declarations
				 *------------------------------------------------------------------------------*/
				#pragma region Private Member Declarations

				FILE *		_fileHandle;
				long		_fileSize;

				void		UnmanagedOpen( CString pszFilename, CString pszMode );
				void		UnmanagedOpen( FILE *fileHandle );
				CString		CalculateModeString(FileMode mode, FileAccess access );

				#pragma endregion

			};
		}
	}
}